# -*- coding: UTF-8 -*-
"""
dec:数据库操作类
@note:
1、执行带参数的sql时，请先用sql语句指定需要输入的条件列表，然后再用tuple/list进行条件批配
2、在格式sql中不需要使用引号指定数据类型，系统会根据输入参数自动识别
3、在输入的值中不需要使用转意函数，系统会自动处理
"""
 
"""
config是系统的全局参数
"""
import pymysql
from pymysql.cursors import DictCursor
from DBUtils.PooledDB import PooledDB
import url_crawler.settings as settings


class MysqlUtil(object):
    """
        MYSQL数据库对象，负责产生数据库连接 , 此类中的连接采用连接池实现
        获取连接对象：conn = Mysql.getConn()
        释放连接对象;conn.close()或del conn
    """
    #连接池
    __pool = None
    def __init__(self):
        """
       数据库构造函数，从连接池中取出连接，并生成操作游标
        """
        self._conn = MysqlUtil.__getConn()
        self._cursor = self._conn.cursor()
 
    @classmethod
    def __getConn(cls):
        """
        @summary: 静态方法，从连接池中取出连接
        @return MySQLdb.connection
        """
        if cls.__pool is None:
            cls.__pool = PooledDB(creator=pymysql, mincached=5, maxcached=100 ,
                              host=settings.DB_HOST, port=int(settings.DB_PORT) ,  # @UndefinedVariable,actually defined
                              user=settings.DB_USER, passwd=settings.DB_PASSWORD ,  # @UndefinedVariable
                              db=settings.DB_NAME,use_unicode=False,  # @UndefinedVariable
                              charset=settings.DB_CHARSET,cursorclass=DictCursor)  # @UndefinedVariable
        return cls.__pool.connection()
 
    def getAll(self,sql,param=None):
        """
        @summary: 执行查询，并取出所有结果集
        @param sql:查询ＳＱＬ，如果有查询条件，请只指定条件列表，并将条件值使用参数[param]传递进来
        @param param: 可选参数，条件列表值（元组/列表）
        @return: result list/boolean 查询到的结果集
        """
        if param is None:
            count = self._cursor.execute(sql)
        else:
            count = self._cursor.execute(sql,param)
        if count>0:
            result = self._cursor.fetchall()
        else:
            result = False
        return result
 
    def getOne(self,sql,param=None):
        """
        @summary: 执行查询，并取出第一条
        @param sql:查询ＳＱＬ，如果有查询条件，请只指定条件列表，并将条件值使用参数[param]传递进来
        @param param: 可选参数，条件列表值（元组/列表）
        @return: result list/boolean 查询到的结果集
        """
        if param is None:
            count = self._cursor.execute(sql)
        else:
            count = self._cursor.execute(sql,param)
        if count>0:
            result = self._cursor.fetchone()
        else:
            result = False
        return result
 
    def getMany(self,sql,num,param=None):
        """
        @summary: 执行查询，并取出num条结果
        @param sql:查询sql，如果有查询条件，请只指定条件列表，并将条件值使用参数[param]传递进来
        @param num:取得的结果条数
        @param param: 可选参数，条件列表值（元组/列表）
        @return: result list/boolean 查询到的结果集
        """
        if param is None:
            count = self._cursor.execute(sql)
        else:
            count = self._cursor.execute(sql,param)
        if count>0:
            result = self._cursor.fetchmany(num)
        else:
            result = False
        return result
    
    def insertOne(self,sql,value):
        """
        @summary: 向数据表插入一条记录
        @param sql:要插入的sql格式
        @param value:要插入的记录数据tuple/list
        @return: insertId 新产生的id
        """
        self._cursor.execute(sql,value)
        return self.__getInsertId()
 
    def insertMany(self,sql,values):
        """
        @summary: 向数据表插入多条记录
        @param sql:要插入的ＳＱＬ格式
        @param values:要插入的记录数据tuple(tuple)/list[list]
        @return: count 受影响的行数
        """
        count = self._cursor.executemany(sql,values)
        return count
 
    def __getInsertId(self):
        """
        获取当前连接最后一次插入操作生成的id,如果没有则为０
        """
        self._cursor.execute("SELECT @@IDENTITY AS id")
        result = self._cursor.fetchall()
        return result[0]['id']
 
    def __query(self,sql,param=None):
        if param is None:
            count = self._cursor.execute(sql)
        else:
            count = self._cursor.execute(sql,param)
        return count
 
    def update(self,sql,param=None):
        """
        @summary: 更新数据表记录
        @param sql: sql格式及条件，使用(%s,%s)
        @param param: 要更新的  值 tuple/list
        @return: count 受影响的行数
        """
        return self.__query(sql,param)
 
    def delete(self,sql,param=None):
        """
        @summary: 删除数据表记录
        @param sql: sql格式及条件，使用(%s,%s)
        @param param: 要删除的条件 值 tuple/list
        @return: count 受影响的行数
        """
        return self.__query(sql,param)
 
    def begin(self):
        """
        @summary: 开启事务
        """
        self._conn.autocommit(0)
 
    def end(self,option='commit'):
        """
        @summary: 结束事务
        """
        if option=='commit':
            self._conn.commit()
        else:
            self._conn.rollback()
 
    def dispose(self,isEnd=1):
        """
        @summary: 释放连接池资源
        """
        if isEnd==1:
            self.end('commit')
        else:
            self.end('rollback')
        self._cursor.close()
        self._conn.close()
    
    @classmethod     
    def close(cls):
        if cls.__pool != None:    
            cls.__pool.close()
            cls.__pool=None
